// purchaseContract.js
import { CsDouble } from '../common/csDouble.js';
import { CsFundDouble } from '../common/csFundDouble.js';
import { Definition } from '../common/definition.js';
import { DocBase } from '../common/docBase.js';
import { CommonOrderStatus, DocType, ProgressState } from '../common/docDefinition.js';
import { Engine } from '../engine.js';
import { FundAccount } from '../funds/fundAccount.js';
import { PendingPaymentOrder } from '../funds/pendingPaymentOrder.js';
import { PendingInventory } from '../inventory/pendingInventory.js';
import { WareHouse } from '../inventory/warehouse.js';
import { TargetObject, TargetObjectPlatformType, TargetObjectType } from '../targetOrg/targetObject.js';
import { Util } from '../../utils/util.js';
import { OrderUtil } from '../../utils/orderUtil.js';
import { CommodityBatchWithTax } from '../sales/sales.js';
import { FunctionPermissionDefinition } from '../platform/functionPermissionDefinition.js';
import { DealFilter } from '../sales/dealFilter.js';
import { OrderSelfDefFundData } from '../funds/orderSelfDefFundData.js';
import { OrderOtherFundData } from '../funds/orderOtherFundData.js';
import {MetalPurchaseTradeMode} from '../common/metalDefinition.js';

/**
 * 采购过滤条件
 */
export class PurchaseFilter extends DealFilter {
    /**
     * 构造函数
     * @param {string|null} storeId 
     */
    constructor(storeId = null) {
        super(storeId);
    }

    /**
     * 克隆过滤器
     * @param {PurchaseFilter} filter 
     * @returns {PurchaseFilter}
     */
    static clone(filter) {
        let baseFilter = super.clone(filter);
        let instance = new PurchaseFilter();
        Object.assign(instance, baseFilter);
        return instance;
    }

    /**
     * 转换为JSON对象
     * @param {boolean} withState 
     * @returns {Object}
     */
    toJson(withState = false) {
        const ret = super.toJson(withState);
        return ret;
    }
}

/**
 * 采购合同/采购单
 */
export class PurchaseContract extends DocBase {
    /** @type {PurchaseContract|null} 编辑前的订单 */
    _orderBeforeEdit = null;

    /** @type {TargetObject} 供应商 */
    _supplier;

    /** @type {WareHouse} 入库仓库 */
    wareHouse;

    /** @type {Array<CommodityBatchWithTax>} 商品列表 */
    _commmodityList = [];

    /** @type {CsDouble} 商品数量 */
    _quantity;

    /** @type {CsFundDouble} 商品金额 */
    _commodityPrice;

    /** @type {CsFundDouble} 含税价 */
    _priceWithTax;

    /** @type {CsFundDouble} 其他费用 */
    _otherCost;

    /** @type {CsFundDouble} 优惠金额 */
    _discount;

    /** @type {CsFundDouble|null} 现结款 (单内) */
    _payedMount = null;

    /** @type {CsFundDouble} 应付余款 (单内) */
    _remainAmount;

    /** @type {CsFundDouble} 总计费用 */
    _totalMount;

    /** @type {boolean} 税额计入成本  开启含税税详情，新建是默认为true*/
    _taxAsCommodityCost;

    /** @type {PendingInventory|null} 入库信息 */
    inventory = null;

    /** @type {PendingPaymentOrder|null} 付款信息 */
    paymentOrder = null;

    /** @type {ProgressState} 支付状态 */
    paymentProgress = ProgressState.None;

    /** @type {ProgressState} 入库状态 */
    inventoryProgress = ProgressState.None;

    /** @type {CsDouble} 折扣比例(0-100) */
    _discountRatio;

    /** @type {CsFundDouble|null} 预付冲抵  为空则默认用于冲抵*/
    _prePaymentOffset = null;

    /** @type {boolean} 直接出库模式 */
    _quickInventoryMode;

    /** @type {boolean} 使能预付冲抵 */
    _enablePrePaymentOffset = false;

    /** @type {FundAccount} 付款资金账户信息 */
    fundAccount;

    /** @type {OrderSelfDefFundData} 贵金属资金账户 */
    _metalFundsPrice;

    /** @type {OrderOtherFundData} 其他费用, 支付费用增加 */
    _otherFundsMorePrice;

    /** @type {OrderOtherFundData} 其他费用，支付费用减少 */
    _otherFundsLessPrice;



    /**
     * 构造函数
     */
    constructor({
        supplier,
        wareHouse,
        commmodityList = [], // List<CommodityBatchWithTax>
        inventory = null,
        paymentOrder = null,
        purchaseDate = new Date(),
        otherCost = CsFundDouble.zero(),
        discout = CsFundDouble.zero(),
        payedMount = null,
        quantity = CsDouble.zero(),
        totalMount = CsFundDouble.zero(),
        commodityPrice = CsFundDouble.zero(),
        paymentProgress = ProgressState.None,
        inventoryProgress = ProgressState.None,
        remainAmount = CsFundDouble.zero(),
        priceWithTax = CsFundDouble.zero(),
        taxAsCommodityCost = null,
        fundAccount = FundAccount.empty(),
        discountRatio = 100,
        quickInventoryMode = null,
        prePaymentOffset = null,

        // super
        id = "",
        storeId = "",
        storeName = "",
        remark = "",
        operator = "",
        operatorId = "",
        docMaker = "",
        status = CommonOrderStatus.WaitReview,
        title = "",
        docCode = "",
        parentDocType = null,
        parentDocCode = "",
        parentDocTitle = "",
        sourceDocType = null,
        sourceDocCode = "",
        sourceDocTitle = "",
        recordDate = null,

        // 初始化方式
        initWithCal = true, // 是否需要计算，从后台来的数据初始化时不需要计算

        metalFundsPrice, // = new OrderSelfDefFundData(),
        otherFundsMorePrice, // = new OrderOtherFundData(),
        otherFundsLessPrice, // = new OrderOtherFundData(),
    } = {}) {
        super({
            id,
            title,
            docCode,
            storeId,
            storeName,
            status,
            docType: DocType.CGD,
            parentDocType,
            parentDocCode,
            parentDocTitle,
            sourceDocCode,
            sourceDocType,
            sourceDocTitle,
            recordDateTime: recordDate,
            operator,
            operatorId,
            docMaker,
            operateDateTime: purchaseDate,
            remark
        });

        this._supplier = supplier;
        this.wareHouse = wareHouse;
        this._commmodityList = commmodityList;
        this.inventory = inventory;
        this.paymentOrder = paymentOrder;
        this.paymentProgress = paymentProgress;
        this.inventoryProgress = inventoryProgress;
        this._otherCost = otherCost;
        this._discount = discout;
        this._payedMount = payedMount;
        this._quantity = quantity;
        this._commodityPrice = commodityPrice;
        this._totalMount = totalMount;
        this._remainAmount = remainAmount;
        this._priceWithTax = priceWithTax;
        this._taxAsCommodityCost = taxAsCommodityCost !== null
            ? taxAsCommodityCost
            : Engine.getOrgSettings().enablePurchaseWithTaxDetail;
        this.fundAccount = fundAccount;
        this._discountRatio = new CsDouble(discountRatio, { precision: Definition.gConstDiscountRatePrecision });
        this._quickInventoryMode = quickInventoryMode !== null
            ? quickInventoryMode
            : OrderUtil.getPurchaseOrderInentoryHandleMethod();
        this._prePaymentOffset = prePaymentOffset;

        this._metalFundsPrice = metalFundsPrice ?? new OrderSelfDefFundData();
        this._otherFundsMorePrice = otherFundsMorePrice ?? new OrderOtherFundData();
        this._otherFundsLessPrice = otherFundsLessPrice ?? new OrderOtherFundData();

        // 计算价格和数量
        if (initWithCal) {
            this.calculatePriceAndQuantity();
        }

        // 如果有冲抵，则使能预付
        if(this._prePaymentOffset != null && this._prePaymentOffset.value != 0){
            this._enablePrePaymentOffset = true;
        }
    }

    get metalFundsPrice() {
        return this._metalFundsPrice;
    }
    /**
     * 设置编辑前的订单
     * @param {PurchaseContract|null} orderBeforeEdit 
     */
    set orderBeforeEdit(orderBeforeEdit) {
        this._orderBeforeEdit = orderBeforeEdit;
    }

    /**
     * 获取/设置供应商
     */
    get supplier() {
        return this._supplier;
    }

    set supplier(supplier) {
        if (this._supplier?.id !== supplier.id) {
            this._supplier = supplier;
            // 切换供应商，重置预收冲抵
            this._prePaymentOffset = null;
            this.calculatePriceAndQuantity();
        }

        if (this._supplier?.platformType === TargetObjectPlatformType.TPlatformCreated) {
            // 平台创建客户，只能全款收取金额
            this._payedMount = null;
        }
    }

    /**
     * 进入编辑状态，检测平台客户金额
     */
    enterEditMode() {
        if (this._supplier.platformType === TargetObjectPlatformType.TPlatformCreated) {
            // 平台创建客户，只能全款收取金额
            this._payedMount = null;
        }
    }

    /**
     * 获取供应商可用预付冲抵金额
     * DML 2025-09-01 弃用， 改用 supplierFundAmount 使用 fundAmount
     * @returns {number}
     */

    get supplierPrePaymentAmount_drop() {
        if (this._orderBeforeEdit &&
            this._orderBeforeEdit.supplier.id === this.supplier.id &&
            this._orderBeforeEdit.status.code === CommonOrderStatus.Passed.code &&
            this._orderBeforeEdit.id === this.id) {
            // 已审核的单据编辑，对于相同的供应商
            // 可用预付冲抵金额 = 供应商可用预付冲抵金额 + 单据之前冲抵金额
            return (this.supplier.prePayment?.value || 0) +
                (this._orderBeforeEdit.prePaymentOffsetOriginal?.value || 0);
        } else {
            return this.supplier?.prePayment?.value || 0;
        }
    }

    // 获取供应商的资金账户金额
    get supplierPrePaymentAmount() {
        if (this._orderBeforeEdit &&
            this._orderBeforeEdit.supplier.id === this.supplier.id &&
            this._orderBeforeEdit.status.code === CommonOrderStatus.Passed.code &&
            this._orderBeforeEdit.id === this.id) {
            // 已审核的单据编辑，对于相同的供应商
            // 可用预付冲抵金额 = 供应商可用预付冲抵金额 + 单据之前冲抵金额
            return (this.supplier.fundAmount?.value || 0) +
                (this._orderBeforeEdit.prePaymentOffsetOriginal?.value || 0);
        } else {
            return this.supplier?.fundAmount?.value || 0;
        }
    }

    /**
     * 商品含税费用
     */
    get commodityPriceWithTax() {
        return this._priceWithTax;
    }

    /**
     * 是否支持含税详情
     * 设定了含税或是该单据已经含税
     */
    get isSupportDetailWithTax() {
        return Engine.getOrgSettings().enablePurchaseWithTaxDetail || this.tax.value !== 0;
    }

    /**
     * 整单折扣率
     */
    get discountRatio() {
        return this._discountRatio;
    }

    set discountRatio(value) {
        this._discountRatio = new CsDouble(
            value.value,
            { precision: Definition.gConstDiscountRatePrecision }
        );
        this.calculatePriceAndQuantity();
    }

    /**
     * 折扣比例小数，用于计算
     */
    get discountRatioForCalc() {
        return this._discountRatio.div(new CsDouble(100));
    }

    /**
     * 预付冲抵 原始对象
     */
    get prePaymentOffsetOriginal() {
        return this._prePaymentOffset;
    }

    /**
     * 预收冲抵
     * 已有冲抵，返回已有冲抵金额
     * 未设置冲抵金额，查看是否开启冲抵开关
     * 开启则按最大冲抵金额返回
     */
    get prePaymentOffset() {
        if (this._prePaymentOffset != null) {
            return this._prePaymentOffset;
        } else {
            if (this._enablePrePaymentOffset && this.supplierPrePaymentAmount < 0) {
                // 开启预收冲抵，返回最大冲抵金额
                let prePaymentAmount = this.supplierPrePaymentAmount;
                return Math.abs(prePaymentAmount) > this.totalMount.value
                    ? new CsFundDouble(-this.totalMount.value)
                    : new CsFundDouble(prePaymentAmount);
            }
            return new CsFundDouble(0);
        }
    }

    /**
     * 直接出库模式
     */
    get quickInventoryMode() {
        return this._quickInventoryMode;
    }

    set quickInventoryMode(value) {
        this._quickInventoryMode = value;
    }

    /**
     * 使能预收冲抵
     */
    get enablePrePaymentOffset() {
        return this._enablePrePaymentOffset;
    }

    set enablePrePaymentOffset(value) {
        this._enablePrePaymentOffset = value;
        if (!value) {
            this._prePaymentOffset = null;
        }
        this.calculatePriceAndQuantity();
    }

    /**
     * 商品数量
     */
    get quantity() {
        return this._quantity;
    }

    /**
     * 商品金额不含税
     */
    get commodityPrice() {
        return this._commodityPrice;
    }

    /**
     * 含税金额
     */
    get priceWithTax() {
        return this._priceWithTax;
    }

    /**
     * 税额
     */
    get tax() {
        return this._priceWithTax.sub(this._commodityPrice);
    }

    /**
     * 税额计入成本 开启含税税详情，新建是默认为true
     */
    get taxAsCommodityCost() {
        return this._taxAsCommodityCost;
    }

    set taxAsCommodityCost(value) {
        this._taxAsCommodityCost = value;
    }

    /**
     * 其他费用
     */
    get otherCost() {
        return this._otherCost;
    }

    set otherCost(value) {
        this._otherCost = value;
        this.calculatePriceAndQuantity();
    }

    get otherFundsMorePrice() {
        return this._otherFundsMorePrice;
    }

    get otherFundsLessPrice() {
        return this._otherFundsLessPrice;
    }

    /**
     * 优惠金额
     */
    get discount() {
        return this._discount;
    }

    set discount(value) {
        this._discount = value;
        this.calculatePriceAndQuantity();
    }

    /**
     * 现结款
     * 如果未设定，则为全部款项
     */
    get payedMount() {
        if (Engine.getOrgSettings().enablePurchaseFullPayment ||
            this.supplier.platformType === TargetObjectPlatformType.TPlatformCreated) {
            // 零售客户返回收款全额
            return this._payedMount ?? this._totalMount.add(this.prePaymentOffset);
        } else {
            return this._payedMount ?? new CsFundDouble(0);
        }
    }

    set payedMount(value) {
        this._payedMount = value;
        this.calculatePriceAndQuantity();
    }

    // 单据应付款 = totalMount 扣除 欠款抵扣
    get payableMount() {
        return this._totalMount.add(this.prePaymentOffset);
    }

    /**
     * 抹零
     * 将订单金额零头计算并填充到优惠金额实现抹零
     */
    setDiscountValueWithSmallChange() {
        let value = this._priceWithTax.value * this.discountRatioForCalc.value
        value += this.otherCost.value;
        value += this._otherFundsMorePrice.value.value;
        value -= this._otherFundsLessPrice.value.value;

        let discountValue = value - Math.floor(value);

        this.discount = new CsFundDouble(discountValue);
        this.calculatePriceAndQuantity();
    }


    /**
     * 实际收款
     * @param {boolean} editMode 
     * @returns {CsFundDouble}
     */
    totalPayedMount(editMode) {
        if (editMode || !this.paymentOrder || Util.isEmpty(this.paymentOrder.id)) {
            return new CsFundDouble(this._allHeXiaoAmount);
        } else {
            return new CsFundDouble(this.paymentOrder.payedMount);
        }
    }

    /**
     * 单据内已核销金额
     * @returns {number}
     */
    get _allHeXiaoAmount() {
        let value = 0;
        value -= this.prePaymentOffset.value;
        value += this.payedMount.value;
        return value;
    }

    /**
     * 应付余款
     */
    get remainAmount() {
        return this._remainAmount;
    }

    /**
     * 应付余款(多单核销后)
     */
    get remainAmountWithAllHeXiao() {
        if (this.paymentOrder && !Util.isEmpty(this.paymentOrder.id)) {
            // 已审核单据采用待收款单据获取多单核销金额
            return this.paymentOrder.pendingPayMount;
        } else {
            // 未审核单据只有本单核销金额
            return this._totalMount.value - this._allHeXiaoAmount;
        }
    }

    /**
     * 总计费用
     */
    get totalMount() {
        return this._totalMount;
    }

    /**
     * 优惠金额（单内）
     */
    get totalDiscountAmount() {
        return this._priceWithTax.add(this._otherCost).add(this._otherFundsMorePrice.value).sub(this._otherFundsLessPrice).sub(this._totalMount);
    }

    /**
     * 是否支持收款金额设定
     */
    get isSupportPayedMountSetting() {
        return this.supplier.platformType !== TargetObjectPlatformType.TPlatformCreated;
    }

    /**
     * 更新商品列表
     * @param {Array<CommodityBatchWithTax>} list 
     */
    updateCommodityList(list) {
        this._commmodityList = [...list];
        this.calculatePriceAndQuantity();
    }

    /**
     * 商品列表
     */
    get commmodityList() {
        return this._commmodityList;
    }

    /**
     * 插入 batch
     * @param {CommodityBatchWithTax} batch 
     */
    addCommodityBatch(batch) {
        this._commmodityList.push(batch);
        this.calculatePriceAndQuantity();
    }

    /**
     * 插入 batch 或是更新数量
     * 没有该商品，添加，如果有则增加数量
     * @param {CommodityBatchWithTax} batch 
     */
    addOrUpdateCommodityBatch(batch) {
        const existing = this._commmodityList.find(element => element.commodity.id === batch.commodity.id);
        if (existing) {
            existing.addCount(new CsDouble(1));
        } else {
            this._commmodityList.push(batch);
            // 增加0， 触发内部价格计算
            existing.addCount(new CsDouble(0));
        }
        this.calculatePriceAndQuantity();
    }

    /**
     * 是否是多条记录
     * @param {CommodityBatchWithTax} batch 
     * @returns {boolean}
     */
    isMultiRecord(batch) {
        return this._commmodityList
            .filter(element => element.commodity.id === batch.commodity.id)
            .length > 1;
    }

    /**
     * 更新batch
     * @param {CommodityBatchWithTax} batch 
     * @param {CommodityBatchWithTax} orgBatch 
     * @returns {boolean}
     */
    updateCommodityBatch(batch, orgBatch) {
        let ret = false;
        const index = this._commmodityList.indexOf(orgBatch);
        if (index >= 0) {
            this._commmodityList[index] = batch;
            ret = true;
        }
        this.calculatePriceAndQuantity();
        return ret;
    }

    /**
     * 删除batch
     * @param {CommodityBatchWithTax} batch 
     * @returns {boolean}
     */
    removeCommodityBatch(batch) {
        const index = this._commmodityList.indexOf(batch);
        const ret = index > -1;
        if (ret) {
            this._commmodityList.splice(index, 1);
        }
        this.calculatePriceAndQuantity();
        return ret;
    }

    /**
     * 清除商品  -- 目前自动化测试用
     */
    clearCommodityBatch() {
        this._commmodityList = [];
        this.calculatePriceAndQuantity();
    }

    /**
     * 判断整单优惠金额有效性
     * @returns {string|null} Error message if invalid, null if valid
     */
    validateDiscountAmount() {
        const maxDiscount = this.priceWithTax.value * this.discountRatioForCalc.value;
        if (this.discount.value > maxDiscount) {
            return `优惠金额大于折后金额 ${new CsFundDouble(maxDiscount).value}`;
        }
        return null;
    }

    /**
     * 判断整单金额有效性
     * @returns {string|null} Error message if invalid, null if valid
     */
    /*
    validateTotalAmount() {
        if (this._remainAmount.value < 0 && this.prePaymentOffset.value > 0) {
            return `实付金额大于单据金额，请检测本次付款金额，该金额应该小于等于单据 (应付金额 - 预付冲抵金额)。即 (0.00-${Util.getFundString((this._totalMount.sub(this.prePaymentOffset)).value, { currencyCharector: false })})`;
        } else if (this._remainAmount.value < 0) {
            return "本次付款金额大于应付金额";
        }
        return null;
    }
        */

    checkTotalAmount() {
        if (this._remainAmount.value < 0 && this.prePaymentOffset.value > 0) {
            return `实付金额+欠款冲抵金额 > 应付金额。超出金额为: ${Util.getFundString(-this._remainAmount.value)}, 超出部分将存入用户存欠款资金账户!`;
        } else if (this._remainAmount.value < 0) {
            return `本次付款金额大于应付金额。超出金额为: ${Util.getFundString(-this._remainAmount.value)}, 超出部分将存入用户存欠款资金账户!`;
        }
        return null;
    }

    /** 校验单据合法性 */
    validateOrder() {
        // 商品校验
        if (this._commmodityList.length == 0) {
            return { errorMsg: "请选择商品!" };
        }
        // 判断商品数量

        // 商品数量校验 DML 2025-09-01 新增空商品列，可能有商品列表，但是没有商品
        let withoutCommodity = true;
        for (let comRrd of this._commmodityList) {
            if (comRrd.commodity && comRrd.count.value == 0) {
                return { errorMsg: "商品[" + comRrd.commodity?.name + "]数量为0, 请调整商品数量!" };
            }

            if (comRrd.commodity && comRrd.count.value > 0) {
                withoutCommodity = false;
            }
        }

        if (withoutCommodity) {
            return { errorMsg: "请选择商品!" };
        }

        // 优惠金额校验
        let disCountErrorMsg = this.validateDiscountAmount();
        if (disCountErrorMsg) {
            return { msgBoxConfirm: true, errorMsg: disCountErrorMsg }
        }

        // 收款金额校验
        let totalWarning = this.checkTotalAmount();
        if (totalWarning) {
            return {
                msgBoxConfirm: true,
                warningMsg: totalWarning
            }
        }

        return null;
    }

    /**
     * 判断是否可以编辑
     * @returns {string|null} Error message if not editable, null if editable
     */
    validateEditAble() {
        let hintCode = 0;

        if (this.inventory && this.inventory.inventoryInList.length > 0) {
            hintCode = 1;
        }

        if (this.paymentOrder && this.paymentOrder.hasUserPaymentOrder) {
            hintCode += 10;
        }

        switch (hintCode) {
            case 0:
                return null;
            case 1:
                return "采购单据有关联入库单据，请先删除关联入库单据!";
            case 10:
                return "采购单据有关联付款单据，请先删除关联付款单据!";
            case 11:
                return "采购单据有关联入库和付款单据，请先删除关联入库和付款单据!";
            default:
                return null;
        }
    } 

    // 过去结算贵金属信息
    // 1  _commmodityList 中的记录 isMetalTradeBatch = true
    // 2 _commmodityList 中的记录 metalPurchaseTradeMode?.code === MetalPurchaseTradeMode.SettleMetal.code
    // 3 累计相同贵金属的折后重量
    // 返回列表字符串，commodity.commodity.standard + commodity.batchPriceWithDiscount.value
    getSettledMetalInfo() { 
        return this._commmodityList.filter(item => item.isMetalTradeBatch && item.metalPurchaseTradeMode?.code === MetalPurchaseTradeMode.SettleMetal.code).map(item => item.commodity.standard + item.countAfterDiscount.value + 'g').join(",");
    }
    
    // 是否包含结价内容
    get hasSettledMetal() { 
        return this._commmodityList.some(item => item.isMetalTradeBatch && item.metalPurchaseTradeMode?.code === MetalPurchaseTradeMode.SettleMetal.code);
    }

    
    

    /**
     * 更新数量和金额
     */
    calculatePriceAndQuantity() {
        //console.log("purchase contract calculatePriceAndQuantity");
        // 计算价格和数量
        this._commodityPrice = CsFundDouble.zero();
        this._quantity = CsDouble.zero();
        this._priceWithTax = CsFundDouble.zero();

        this._metalFundsPrice.clear();

        this._commmodityList.forEach(element => {
            // 如果是贵金属非结价，则通过metalFundAccountPrice 计算贵金属金额
            this._quantity = this._quantity.add(element.count);

            if (element.isMetalTradeBatch) {
                this._metalFundsPrice.addCommodityBatch(element);
            }

            // 结价模式，价格计入总价
            if (element.isSettlePrice) {
                this._commodityPrice = this._commodityPrice.add(element.batchPriceWithDiscount);
                this._priceWithTax = this._priceWithTax.add(element.batchPriceWithTax);
            }
        });

        this._totalMount = new CsFundDouble(this._priceWithTax.value * this.discountRatioForCalc.value)
            .add(this._otherCost)
            .add(this._otherFundsMorePrice.value)
            .sub(this._otherFundsLessPrice.value)
            .sub(this._discount);

        this._remainAmount = this._totalMount.sub(this.payedMount).add(this.prePaymentOffset);
    }

    /**
     * Check if user has read permission
     * @returns {boolean} 
     */
    static hasReadPermission() {
        return Engine.profile.permissionMgr.hasPermission([
            FunctionPermissionDefinition.P_PurchaseContract_Read,
            FunctionPermissionDefinition.P_PurchaseContract_Edit,
            FunctionPermissionDefinition.P_PurchaseContract_Audit
        ]);
    }

    /**
     * Check if user has edit permission
     * @returns {boolean}
     */
    static hasEditPermission() {
        if (Engine.getOrgSettings().enablePurchaseRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_PurchaseContract_Edit,
                FunctionPermissionDefinition.P_PurchaseContract_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_PurchaseContract_Edit
            ]);
        }
    }
    /**
     * Check if user has audit permission 
     * @returns {boolean}
     */
    static hasAuditPermission() {
        if (Engine.getOrgSettings().enablePurchaseRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_PurchaseContract_Edit,
                FunctionPermissionDefinition.P_PurchaseContract_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_PurchaseContract_Audit
            ]);
        }
    }

    /**
 * Check if user has read permission
 * @returns {boolean} 
 */
    static hasMetalOrderReadPermission() {
        return Engine.profile.permissionMgr.hasPermission([
            FunctionPermissionDefinition.P_MetalContractManufactoring_Read,
            FunctionPermissionDefinition.P_MetalContractManufactoring_Edit,
            FunctionPermissionDefinition.P_MetalContractManufactoring_Audit
        ]);
    }

    /**
     * Check if user has edit permission
     * @returns {boolean}
     */
    static hasMetalOrderEditPermission() {
        if (Engine.getOrgSettings().enablePurchaseRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalContractManufactoring_Edit,
                FunctionPermissionDefinition.P_MetalContractManufactoring_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalContractManufactoring_Edit
            ]);
        }
    }
    /**
     * Check if user has audit permission 
     * @returns {boolean}
     */
    static hasMetalOrderAuditPermission() {
        if (Engine.getOrgSettings().enablePurchaseRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalContractManufactoring_Edit,
                FunctionPermissionDefinition.P_MetalContractManufactoring_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalContractManufactoring_Audit
            ]);
        }
    }

    /**
     * 创建空采购合同
     * @param {Object} options
     * @returns {PurchaseContract}
     */
    static empty({
        operator = null,
        operatorId = null,
        storeId = null,
        storeName = null
    } = {}) {
        const contract = new PurchaseContract({
            supplier: null, //todo 临时取消  TargetObject.empty({ objType: TargetObjectType.TSupplier }),
            wareHouse: WareHouse.empty(),
            otherCost: CsFundDouble.zero(),
            discout: CsFundDouble.zero(),
            remainAmount: CsFundDouble.zero(),
            totalMount: CsFundDouble.zero(),
            payedMount: null,
            quantity: CsDouble.zero(),
            priceWithTax: CsFundDouble.zero(),
            commodityPrice: CsFundDouble.zero(),
            commmodityList: [],
            paymentProgress: ProgressState.None,
            inventoryProgress: ProgressState.None,
            taxAsCommodityCost: Engine.getOrgSettings().enablePurchaseWithTaxDetail,
            fundAccount: FundAccount.empty(),
            discountRatio: 100,
            quickInventoryMode: OrderUtil.getPurchaseOrderInentoryHandleMethod(),
            supplierPrePaymentAmount: 0,
            operator: operator,
            operatorId: operatorId,
            storeId: storeId,
            storeName: storeName,


        });

        contract.wareHouse = OrderUtil.getOrderDefaultWarehouse({
            storeId: contract.storeId,
            curWarehouse: contract.wareHouse
        });

        contract.fundAccount = OrderUtil.getOrderDefaultFundAccount({
            storeId: contract.storeId,
            curFundAccount: contract.fundAccount
        });

        // 设置默认供应商为临时供应商
        contract.supplier = OrderUtil.getOrderDefaultSupplier({
            curSupplier: contract.supplier
        });


        return contract;
    }

    /**
     * 克隆采购合同
     * @param {PurchaseContract} pc
     * @returns {PurchaseContract}
     */
    static clone(source) {
        let baseOrder = DocBase.clone(source);

        const contract = new PurchaseContract({
            supplier: TargetObject.clone(source._supplier),
            wareHouse: WareHouse.clone(source.wareHouse),
            otherCost: source._otherCost,
            discout: source._discount,
            remainAmount: source._remainAmount,
            payedMount: source._payedMount ? source._payedMount.value : null,
            quantity: source._quantity,
            commodityPrice: source._commodityPrice,
            totalMount: source._totalMount,
            inventory: source.inventory,
            paymentOrder: source.paymentOrder,
            priceWithTax: source._priceWithTax,
            commmodityList: [],
            paymentProgress: source.paymentProgress,
            inventoryProgress: source.inventoryProgress,
            taxAsCommodityCost: source._taxAsCommodityCost,
            fundAccount: source.fundAccount,
            discountRatio: source._discountRatio,
            quickInventoryMode: source._quickInventoryMode,
            prePaymentOffset: source._prePaymentOffset,
            initWithCal: false,
            metalFundsPrice: source._metalFundsPrice,
            otherFundsMorePrice: source._otherFundsMorePrice,
            otherFundsLessPrice: source._otherFundsLessPrice
        });

        Object.assign(contract, baseOrder);

        // 拷贝商品列表
        source._commmodityList.forEach(element => {
            contract._commmodityList.push(CommodityBatchWithTax.clone(element));
        });

        return contract;
    }

    /**
     * 复制
     * @param {Object} options
     */
    resetForCopy({ removeParentAndSourceData = true } = {}) {
        super.resetForCopy({ removeParentAndSourceData: removeParentAndSourceData });
        // 清除商品列表id
        this._commmodityList.forEach(element => {
            element.id = "";
        });
        // 支付重置
        this._prePaymentOffset = null;
        this._payedMount = null;
        this._enablePrePaymentOffset = false;
        this._orderBeforeEdit = null;
    }

    /**
     * 从JSON创建采购合同
     * @param {Object} json
     * @returns {PurchaseContract}
     */
    static fromJson(json) {
        let baseOrder = DocBase.fromJson(json, DocType.CGD);

        const contract = new PurchaseContract({
            supplier: TargetObject.fromJsonForOrders(json),
            wareHouse: new WareHouse({
                id: Util.jsonToString(json['storageId']),
                name: Util.jsonToString(json['storageName'])
            }),
            commmodityList: [],
            otherCost: Util.jsonToCsFundDouble(json['elsePrice'], 0),
            discout: Util.jsonToCsFundDouble(json['discountPrice'], 0),
            remainAmount: Util.jsonToCsFundDouble(json['payPrice'], 0),
            priceWithTax: CsFundDouble.zero(), // 构造函数中计算
            totalMount: Util.jsonToCsFundDouble(json['orderTotalAmount'], 0),
            commodityPrice: Util.jsonToCsFundDouble(json['commodityTotalAmount'], 0),
            payedMount: Util.jsonToCsFundDouble(json['prePrice'], 0),
            quantity: Util.jsonToCsDouble(json['commodityCount'], 0),
            inventory: json["waitInoutOrder"] == null
                ? PendingInventory.empty()
                : PendingInventory.fromJson(json["waitInoutOrder"]),
            paymentOrder: json["waitPayments"] == null
                ? PendingPaymentOrder.empty()
                : PendingPaymentOrder.fromJson(json["waitPayments"]),
            // 进度
            inventoryProgress: Util.jsonToPorgressState(json['waitInoutProcess'], ProgressState.None),
            // 进度
            paymentProgress: Util.jsonToPorgressState(json['waitPaymentProcess'], ProgressState.None),
            // 付款账户
            fundAccount: new FundAccount({
                id: Util.jsonToString(json['fundAccountId']),
                name: Util.jsonToString(json['fundAccountName']),
                balance: 0,
                bankName: "",
                income: 0,
                expenses: 0
            }),
            // 税作为商品成本, 后台记录没有默认不计税入成本，大多数用户没有这个设置
            taxAsCommodityCost: Util.jsonToBool(json['taxAsCommodityCost'], false),
            quickInventoryMode: Util.jsonToBool(json['quickInventoryMode'], true),
            // 整单优惠
            discountRatio: Util.jsonToCsDouble(json['discountRatio'], 100, Definition.gConstDiscountRatePrecision),
            // 预付冲抵
            prePaymentOffset: Util.jsonToCsFundDouble(json['prePaymentOffset'], 0),
            // 无需计算
            initWithCal: false,
            // 贵金属账户金额
            metalFundsPrice: OrderSelfDefFundData.fromJson(json['metalAccounts']),
            // 其他费用
            otherFundsMorePrice: OrderOtherFundData.fromJson(json['otherFeesMore']),
            otherFundsLessPrice: OrderOtherFundData.fromJson(json['otherFeesLess'])
        });

        Object.assign(contract, baseOrder);

        let tax = Util.jsonToCsFundDouble(json['taxTotalAmount'], 0);
        // 反向计算 _priceWithTax
        contract._priceWithTax = tax.add(contract._commodityPrice);

        // 商品列表
        (json.details || []).forEach(element => {
            contract._commmodityList.push(CommodityBatchWithTax.fromJson(element, contract.docType));
        });

        // 计算价格和数量 (不调用计算，列表页面接口没有返回详情，计算会遍历详情，造成数据为0)
        // calculatePriceAndQuantity();

        /// 详情单据同步详情中对应进度信息
        if (contract.inventory != null &&
            !Util.isEmpty(contract.inventory.id) &&
            contract.inventoryProgress.code != contract.inventory.progressState.code) {
            contract.inventoryProgress = contract.inventory.progressState;
        }        

        return contract;
    }

    /**
     * 转换为JSON
     * @returns {Object}
     */
    toJson() {
        const json = super.toJson();

        json.prePrice = this.payedMount.value;
        json.details = this._commmodityList.filter(element => element.commodity != null).map(element => element.toJson());
        json.commodityTotalAmount = this._commodityPrice.value;
        json.orderTotalAmount = this._totalMount.value;
        json.discountPrice = this._discount.value;
        json.objId = this.supplier.id;
        json.elsePrice = this._otherCost.value;
        json.payPrice = this.remainAmount.value;
        json.storageId = this.wareHouse.id;
        json.taxTotalAmount = this.tax.value;
        json.fundAccountId = this.fundAccount.id;
        json.taxAsCommodityCost = this._taxAsCommodityCost ? 1 : 0;
        json.discountRatio = this._discountRatio.value;
        // 注意 prePaymentOffset 不能采用 _prePaymentOffset 因为有默认值判断
        json.prePaymentOffset = this.prePaymentOffset.value;
        // 系统用户直接出库
        json.quickInventoryMode = this.supplier.platformType == TargetObjectPlatformType.TPlatformCreated
            ? 1
            : (this._quickInventoryMode ? 1 : 0);

        json.metalAccounts = this._metalFundsPrice.toJsonStr();
        json.otherFeesMore = this._otherFundsMorePrice.toJsonStr();
        json.otherFeesLess = this._otherFundsLessPrice.toJsonStr();

        return json;
    }

    /**
     * 转换为打印信息JSON（调试用）
     * @returns {Object}
     */
    toPrintInfoJson() {
        const json = {};

        json.businessTime = DateUtil.getDateTimeTitle(this.operateDate);
        json.commodityTotalAmount = this._commodityPrice.value;
        json.orderTotalAmount = this._totalMount.value;
        if (Util.isEmpty(this.id)) {
            json.createUser = !Util.isEmpty(Engine.profile.nickName)
                ? Engine.profile.nickName
                : Engine.profile.userName;
        }

        json.details = this._commmodityList.map(element => element.toPrintInfoJson());

        json.discountPrice = this._discount.value;
        json.elsePrice = this._otherCost.value;
        json.handleUserId = this.operatorId;
        json.handleUserName = this.operator;
        json.id = this.id;
        json.objId = this.supplier.id;
        json.orderStatus = CommonOrderStatus.values.indexOf(this.status); //单据状态：0待审核,1审核通过，2不通过，3已完成
        json.orderTitle = this.title;
        json.orderType = DocType.values.indexOf(this.docType);
        json.orgId = Engine.profile.org.orgId;
        json.payPrice = this.remainAmount.value;
        json.preOrderId = this.parentDocCode;
        json.prePrice = this.payedMount.value;
        json.remark = this.remark;
        json.sourceOrderId = this.sourceDocCode;
        json.warehouse = this.wareHouse.toJson();
        json.taxTotalAmount = this.tax.value;
        json.updateUser = Engine.profile.nickName;
        json.pendingInventory = this.inventory?.toPrintInfoJson();
        json.paymentOrder = this.paymentOrder?.toPrintInfoJson();
        json.taxAsCommodityCost = this._taxAsCommodityCost;
        json.fundAccount = this.fundAccount.toJson();

        return json;
    }
}